package handling;

import tools.HexTool;

import java.util.*;

public class ExternalCodeTableGetter {
    Properties props;

    public ExternalCodeTableGetter(Properties properties) {
        this.props = properties;
    }

    private static <T extends Enum> T valueOf(String name, T[] values) {
        for (T val : values) {
            if (val.name().equals(name)) {
                return val;
            }
        }
        return null;
    }

    private <T extends Enum> short getValue(String name, T[] values, short def) {
        String prop = this.props.getProperty(name);
        if (prop == null || prop.length() <= 0) {
            return def;
        }
        String trimmed = prop.trim();
        String[] args = trimmed.split(" ");
        int base = 0;
        String offset;
        if (args.length == 2) {
            base = ((WritableIntValueHolder) valueOf(args[0], (T[]) values)).getValue();
            if (base == def) {
                base = this.getValue(args[0], (Enum[]) values, def);
            }
            offset = args[1];
        } else {
            offset = args[0];
        }
        if (offset.length() > 2 && offset.substring(0, 2).equals("0x")) {
            return (short) (Short.parseShort(offset.substring(2), 16) + base);
        }
        return (short) (Short.parseShort(offset) + base);
    }

    public static <T extends Enum> String getOpcodeTable(T[] enumeration) {
        StringBuilder enumVals = new StringBuilder();
        List<T> all = (List<T>) new ArrayList();
        all.addAll((Collection<? extends T>) Arrays.asList(enumeration));
        Collections.sort(all, (Comparator) new Comparator<WritableIntValueHolder>() {
            @Override
            public int compare(WritableIntValueHolder o1, WritableIntValueHolder o2) {
                return Short.valueOf(o1.getValue()).compareTo(Short.valueOf(o2.getValue()));
            }
        });
        for (T code : all) {
            enumVals.append(code.name());
            enumVals.append(" = ");
            enumVals.append("0x");
            enumVals.append(HexTool.toString((int) ((WritableIntValueHolder) code).getValue()));
            enumVals.append(" (");
            enumVals.append((int) ((WritableIntValueHolder) code).getValue());
            enumVals.append(")\n");
        }
        return enumVals.toString();
    }

    public static <T extends Enum> void populateValues(Properties properties, T[] values) {
        ExternalCodeTableGetter exc = new ExternalCodeTableGetter(properties);
        for (T code : values) {
            ((WritableIntValueHolder) code).setValue(exc.getValue(code.name(), values, (short) (-2)));
        }
    }
}
